{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### yied from 子生成器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import namedtuple"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "Result = namedtuple('Result', 'count average')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 子生成器\n",
    "def averager():\n",
    "    total = 0.0\n",
    "    count = 0.0\n",
    "    average = None\n",
    "    while True:\n",
    "        term = yield\n",
    "        if term is None:\n",
    "            break\n",
    "        total += term\n",
    "        count += 1\n",
    "        average = total / count\n",
    "    return Result(count, average)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 委派生成器\n",
    "def grouper(results, key):\n",
    "    while True:\n",
    "        results[key] = yield from averager()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 客户端代码，即调用方\n",
    "def main(data):\n",
    "    results = {}\n",
    "    for key, values in data.items():\n",
    "        group = grouper(results, key)\n",
    "        next(group)\n",
    "        for value in values:\n",
    "            group.send(value)\n",
    "        group.send(None)\n",
    "    # print(results)\n",
    "    report(results)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 输出报告\n",
    "def report(results):\n",
    "    for key, result in sorted(results.items()):\n",
    "        group, unit = key.split(';')\n",
    "        print('{:2} {:5} averaging {:.2f}{}'.format(\n",
    "              result.count, group, result.average, unit))\n",
    "\n",
    "\n",
    "data = {\n",
    "    'girls;kg':\n",
    "        [40.9, 38.5, 44.3, 42.2, 45.2, 41.7, 44.5, 38.0, 40.6, 44.5],\n",
    "    'girls;m':\n",
    "        [1.6, 1.51, 1.4, 1.3, 1.41, 1.39, 1.33, 1.46, 1.45, 1.43],\n",
    "    'boys;kg':\n",
    "        [39.0, 40.8, 43.2, 40.8, 43.1, 38.6, 41.4, 40.6, 36.3],\n",
    "    'boys;m':\n",
    "        [1.38, 1.5, 1.32, 1.25, 1.37, 1.48, 1.25, 1.49, 1.46],\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9.0 boys  averaging 40.42kg\n",
      "9.0 boys  averaging 1.39m\n",
      "10.0 girls averaging 42.04kg\n",
      "10.0 girls averaging 1.43m\n"
     ]
    }
   ],
   "source": [
    "main(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
